package com.ch3cooh.registry.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ch3cooh.rpc.component.LocalServerManager;
import com.ch3cooh.rpc.pojo.ControllerInfo;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import com.ch3cooh.registry.exception.MyZkException;
import com.ch3cooh.registry.pojo.RegisterInfo;
import com.ch3cooh.registry.util.NetworkUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @功能: 向zookeeper注册的服务 相关信息
 * @作者:chanson
 * @时间:2018/4/28 09:10
 */
@Service
@Log
public class RegisterService {

    private static final String REGISTER_PATH = "/register";

    @Autowired
    Environment env;
    @Autowired
    ZkService zkService;
    @Autowired
    LocalServerManager localServerManager;
    /**
     * 创建 RegisterInfo对象
     * @return  RegisterInfo对象
     */
    public RegisterInfo buildRegisterInfo(){
        String host = NetworkUtils.getHost();
        String serverName = env.getProperty("spring.application.name");
        int port = env.getProperty("server.port",int.class);
        String hostUrl = host+":"+port;
        return new RegisterInfo(
                host,
                port,
                NetworkUtils.getComputerName(),
                hostUrl,
                serverName
        );
    }

    /**
     * 将服务名注册到zookeeper上
     * @return
     */
    public  RegisterInfo doRegister(){
        RegisterInfo registerInfo = buildRegisterInfo();
        String path = builFulldRegisterPath(registerInfo);
        String data = JSONObject.toJSONString( buildRegisterInfo() );
        try {
            if( zkService.checkExistsNode(path) ) {
                throw new MyZkException(String.format("已存在同名'%s'的节点,不能再注册",path));
            }
            //创建临时节点
            if(zkService.createEphemeralNode( path,data )){
                //创建成功时，监听该节点
                zkService.addListener(REGISTER_PATH);
                //并将当前已注册的服务信息 同步到本地
            //    syncFromRegistry();
                return registerInfo;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 展示注册的服务信息
     * @return
     */
    public Map<String, List<RegisterInfo>> listRegstry(){
        Map<String, List<String>> rawMap = zkService.listOneLayer(REGISTER_PATH);
        Map<String, List<RegisterInfo>> regstryMap = rawMap.entrySet().stream()
                .collect(Collectors.toMap(
                            e -> e.getKey(),
                            e ->e.getValue().stream().map(str-> JSON.parseObject(str,RegisterInfo.class) ).collect(Collectors.toList())
        ));
        return regstryMap;
    }

    /**
     * 构建 注册节点的 节点名
     * @param registerInfo
     * @return
     */
    public String builFulldRegisterPath(RegisterInfo registerInfo){
        return REGISTER_PATH + "/"+registerInfo.getServerName() + "/"+registerInfo.getHostUrl();
    }

    /**
     * 同步注册中心已注册的服务信息
     * @return
     */
    public boolean syncFromRegistry(){
        Map<String, List<RegisterInfo>> regstryMap = listRegstry();
        Map<String, List<ControllerInfo>> collect = regstryMap.entrySet().stream()
                .collect(Collectors.toMap(
                        e -> e.getKey(),
                        e -> e.getValue().stream().map(e2 -> new ControllerInfo(e2.getServerName(), e2.getHttpHostUrl()))
                                .collect(Collectors.toList())
                ));
        localServerManager.sync(collect);
        log.info("已订阅到当前时间点最新的服务列表");
        return true;
    }

}
